home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / New WASTE Handlers / New Sound Handler / WEObjectSound.c < prev    next >
Text File  |  1996-02-04  |  6KB  |  236 lines

  1. // Sound Object Handler for the WASTE Text Engine
  2. // by Michael F. Kamprath, kamprath@earthlink.net
  3. //     and Chris K. Thomas, ckt@guest.apple.com
  4. //                        or thunderone@delphi.com
  5. // 
  6. // History:
  7. // v1.0, 16 March 1995  MFK - created
  8. //
  9. // v2.0b1:    11 May 1995 CKT
  10. //            almost entirely rewritten for robustness, simplicity,
  11. //            modularity and some flexibility
  12. // v2.0b2:    2-3 June 1995 CKT
  13. //            bug fixes & now works on 68k and minor tweaking.
  14. //        
  15.  
  16. /*
  17.     Features of the new implementation:
  18.     
  19.     • Single click only.  The previous one wanted double
  20.     click. To the user, this is like pressing a button,
  21.     which is a single click operation.
  22.     
  23.     • Improved memory management.
  24.     
  25.     • Added method to stop the currently playing sound.
  26.     
  27.     • Removed a bunch of unnecessary methods.
  28.     
  29.     • Cleaned up the global namespace.
  30.     
  31.     • Can now use any size (square) icon.
  32.     
  33.     • Managed to resist the temptation to C++-ify.  I
  34.     have a great stack-based SndCommand class, though...
  35.     
  36.     In general, we just pollute our environment less and
  37.     manage to run faster anyway. Industrial Strength and
  38.     non-toxic.
  39.     
  40.     - Chris
  41. */
  42.  
  43. #include <Icons.h>
  44. #include <SoundInput.h>
  45. #include "WASTE.h"
  46.  
  47. #include "WEObjectSound.h"
  48.  
  49. // • constants =====================================================================
  50.  
  51. #define kSoundIconID 550
  52. #define kIconSize 16        // * change to 32 for large
  53.  
  54. // • macros ========================================================================
  55.  
  56. #define ThrowIfOSErr_(x) if(x != noErr) goto end;
  57. // * well, okay, I couldn't help using C++ semantics, but there isn't any real C++...                    
  58.  
  59. // • static variables ==============================================================
  60.  
  61. static SndChannelPtr    sSoundChannel = NULL;
  62. static SndListHandle    sCurrentSound = NULL;
  63. static char                sPreviousSoundState;
  64.  
  65. // • static prototypes =============================================================
  66.  
  67. static pascal OSErr    HandleNewSound(Point *defaultObjectSize, WEObjectReference objectRef);
  68. static pascal OSErr    HandleDisposeSound(WEObjectReference objectRef );
  69. static pascal Boolean HandleClickSound(Point hitPt, short modifiers,
  70.                                             long clickTime, WEObjectReference objectRef);
  71. static pascal OSErr    HandleDrawSound(Rect *destRect, WEObjectReference objectRef );
  72.  
  73.  
  74. // • mixedmode =====================================================================
  75.  
  76. static UniversalProcPtr    sNewHandlerRD = NULL;
  77. static UniversalProcPtr    sDisposeHandlerRD = NULL;
  78. static UniversalProcPtr    sDrawHandlerRD = NULL;
  79. static UniversalProcPtr    sClickHandlerRD = NULL;
  80.  
  81. // • implementation  ===============================================================
  82.  
  83. // * Install the sound object handlers
  84. // *    if inChannel is NULL, we create our own.
  85. // *    if not, we use inChannel.
  86.  
  87. OSErr    WEObjSoundInstall(SndChannelPtr    inChannel, WEHandle inWaste)
  88. {
  89.     OSErr theErr = noErr;
  90.     
  91.     if(sNewHandlerRD == NULL)
  92.     {
  93.         sNewHandlerRD = NewWENewObjectProc(HandleNewSound);
  94.         sDisposeHandlerRD = NewWEDisposeObjectProc(HandleDisposeSound);
  95.         sDrawHandlerRD = NewWEDrawObjectProc(HandleDrawSound);
  96.         sClickHandlerRD = NewWEClickObjectProc(HandleClickSound);
  97.     }
  98.     
  99.     if(inChannel == NULL)
  100.     {
  101.         theErr = SndNewChannel(&sSoundChannel, sampledSynth, 0, NULL);
  102.         ThrowIfOSErr_(theErr);
  103.     }
  104.     else
  105.     {
  106.         sSoundChannel = inChannel;
  107.     }
  108.     
  109.     theErr = WEInstallObjectHandler('snd ', weNewHandler, sNewHandlerRD, inWaste);
  110.     ThrowIfOSErr_(theErr);
  111.     theErr = WEInstallObjectHandler('snd ', weDisposeHandler, sDisposeHandlerRD, inWaste);
  112.     ThrowIfOSErr_(theErr);
  113.     theErr = WEInstallObjectHandler('snd ', weDrawHandler, sDrawHandlerRD, inWaste);
  114.     ThrowIfOSErr_(theErr);
  115.     theErr = WEInstallObjectHandler('snd ', weClickHandler, sClickHandlerRD, inWaste);
  116.     ThrowIfOSErr_(theErr);
  117.  
  118. end:
  119.     return theErr;
  120. }
  121.  
  122. // *  New Object Handler for sounds
  123. pascal OSErr    HandleNewSound(Point *defaultObjectSize, WEObjectReference /*objectRef*/)
  124. {
  125.     (*defaultObjectSize).h = kIconSize;
  126.     (*defaultObjectSize).v = kIconSize;
  127.  
  128.     return noErr;
  129. }
  130.  
  131. // * Dispose Object handler for sounds
  132. pascal OSErr    HandleDisposeSound(WEObjectReference objectRef)
  133. {
  134.     SndListHandle    theSound;
  135.     
  136.     theSound = (SndListHandle)WEGetObjectDataHandle(objectRef);
  137.     
  138.     if(theSound == sCurrentSound)    //MFK fix
  139.         WEObjSoundStop();
  140.     
  141.     DisposeHandle((Handle)theSound);
  142.  
  143.     return MemError();
  144. }
  145.  
  146. // * Draw Object handler for sounds
  147. pascal OSErr    HandleDrawSound(Rect *destRect, WEObjectReference /*objectRef*/ )
  148. {
  149.     OSErr    theErr;
  150.     
  151.     theErr = PlotIconID(destRect, atNone, ttNone, kSoundIconID);
  152.     
  153.     return theErr;
  154. }
  155.  
  156. // * Click Object Handler for sounds
  157. pascal Boolean
  158. HandleClickSound(Point /*hitPt*/, short /*modifiers*/, 
  159.                     long /*clickTime*/, WEObjectReference objectRef)
  160. {
  161.     if(sCurrentSound)
  162.     {
  163.         WEObjSoundStop();
  164.     }
  165.  
  166.     sCurrentSound = (SndListHandle)WEGetObjectDataHandle( objectRef );
  167.     
  168.     sPreviousSoundState = HGetState((Handle)sCurrentSound);
  169.     HLockHi((Handle)sCurrentSound);
  170.     
  171.     SndPlay(sSoundChannel, sCurrentSound, true);
  172.     
  173.     return true;
  174. }
  175.  
  176. // • global sound utils ===============================================================
  177.  
  178. // * Uses built in sound recording to create a new sound object.
  179. OSErr    WEObjSoundNew( WEHandle theWE )
  180. {
  181.     OSErr            theErr;
  182.     SndListHandle    sndHandle = nil;
  183.     Point            corner = {kIconSize, kIconSize};
  184.  
  185.     theErr = SndRecord(nil, corner, siGoodQuality, &sndHandle);
  186.     
  187.     if (theErr == noErr)
  188.     {
  189.         corner.h = kIconSize;
  190.         corner.v = kIconSize;
  191.         WEInsertObject( 'snd ', (Handle)sndHandle, corner, theWE );
  192.     }
  193.     
  194.     return( theErr );
  195. }
  196.  
  197. // * idle - Call this at some point in your event loop
  198. // * or through an idle queue etc
  199. void WEObjSoundIdle(void)
  200. {
  201.     if(sCurrentSound)
  202.     {
  203.         SCStatus curStatus;
  204.         
  205.         SndChannelStatus(sSoundChannel, sizeof(SCStatus), &curStatus);
  206.         
  207.         if(!curStatus.scChannelBusy)
  208.             HSetState((Handle)sCurrentSound, sPreviousSoundState);
  209.     }
  210. }
  211.  
  212. // * stop the sound in progress, if any
  213. void WEObjSoundStop(void)
  214. {
  215.     if(sCurrentSound)
  216.     {
  217.         SCStatus curStatus;
  218.         
  219.         SndChannelStatus(sSoundChannel, sizeof(SCStatus), &curStatus);
  220.         
  221.         if(curStatus.scChannelBusy)
  222.         {
  223.             SndCommand ourCmd;
  224.             
  225.             ourCmd.cmd = quietCmd;
  226.             ourCmd.param1 = 0;
  227.             ourCmd.param2 = 0;
  228.             
  229.             (void) SndDoImmediate(sSoundChannel, &ourCmd);
  230.             HSetState((Handle)sCurrentSound, sPreviousSoundState);
  231.             
  232.             // * yes, we're ignoring the error purposely
  233.             
  234.         }
  235.     }
  236. }